package com.yida.gwj.vote.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.yida.common.core.constant.SecurityConstants;
import com.yida.common.core.domain.R;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.utils.CheckRemoteServiceResultUtils;
import com.yida.common.core.utils.DateUtils;
import com.yida.common.core.utils.StringUtils;
import com.yida.common.security.utils.SecurityUtils;
import com.yida.gwj.common.domain.GwjBaseHouse;
import com.yida.gwj.common.domain.GwjBaseOwner;
import com.yida.gwj.common.enums.GwjBusinessHouseStatus;
import com.yida.gwj.common.utils.GwjConvertUtil;
import com.yida.gwj.vote.domain.GwjVoteBuild;
import com.yida.gwj.vote.domain.GwjVoteHouse;
import com.yida.gwj.vote.domain.GwjVoteProject;
import com.yida.gwj.vote.domain.GwjVoteResult;
import com.yida.gwj.vote.domain.dto.*;
import com.yida.gwj.vote.domain.request.GwjVoteAuditRequest;
import com.yida.gwj.vote.domain.request.GwjVoteProjectRequest;
import com.yida.gwj.vote.enums.*;
import com.yida.gwj.vote.mapper.GwjVoteProjectMapper;
import com.yida.gwj.vote.service.*;
import com.yida.system.api.RemoteSmsService;
import com.yida.system.api.domain.SysSms;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 投票项目Service业务层处理
 *
 * @author lqq
 * @date 2023-03-13
 */
@Service
public class GwjVoteProjectServiceImpl implements IGwjVoteProjectService {

    @Resource
    private GwjVoteProjectMapper voteProjectMapper;

    @Resource
    private IGwjVoteTemplateService voteTemplateService;

    @Resource
    private IGwjVoteResultService voteResultService;

    @Resource
    private IGwjVoteHouseService voteHouseService;

    @Resource
    private RemoteSmsService remoteSmsService;

    @Resource
    private IGwjVoteBuildService voteBuildService;

    /**
     * 查询投票项目
     *
     * @param voteId 投票项目主键
     * @return 投票项目
     */
    @Override
    public GwjVoteProject selectVoteProjectByVoteId(Long voteId) {
        return voteProjectMapper.selectVoteProjectByVoteId(voteId);
    }

    /**
     * 查询单条投票项目
     *
     * @param voteProject 投票项目
     * @return 投票项目
     */
    @Override
    public GwjVoteProject selectVoteProject(GwjVoteProject voteProject) {
        return voteProjectMapper.selectVoteProject(voteProject);
    }

    /**
     * 查询投票项目列表
     *
     * @param voteProject 投票项目
     * @return 投票项目
     */
    @Override
    public List<GwjVoteProject> selectVoteProjectList(GwjVoteProject voteProject) {
        return voteProjectMapper.selectVoteProjectList(voteProject);
    }

    /**
     * 新增投票项目
     *
     * @param voteProject 投票项目
     * @return 结果
     */
    @Override
    public int insertVoteProject(GwjVoteProject voteProject) {
        voteProject.setCreateUserId(SecurityUtils.getLoginUser().getSysUser().getUserId());
        voteProject.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getRealName());
        voteProject.setCreateTime(DateUtils.getNowDate());
        return voteProjectMapper.insertVoteProject(voteProject);
    }

    /**
     * 修改投票项目
     *
     * @param voteProject 投票项目
     * @return 结果
     */
    @Override
    public int updateVoteProject(GwjVoteProject voteProject) {
        voteProject.setUpdateBy(SecurityUtils.getLoginUser().getSysUser().getRealName());
        voteProject.setUpdateTime(DateUtils.getNowDate());
        return voteProjectMapper.updateVoteProject(voteProject);
    }

    /**
     * 批量删除投票项目
     *
     * @param voteIds 需要删除的投票项目主键
     * @return 结果
     */
    @Override
    public int deleteVoteProjectByVoteIds(Long[] voteIds) {
        return voteProjectMapper.deleteVoteProjectByVoteIds(voteIds);
    }

    /**
     * 删除投票项目信息
     *
     * @param voteId 投票项目主键
     * @return 结果
     */
    @Override
    public int deleteVoteProjectByVoteId(Long voteId) {
        return voteProjectMapper.deleteVoteProjectByVoteId(voteId);
    }

    /**
     * 新增投票项目
     *
     * @param request 投票项目
     * @param data    基础楼栋房屋业主数据
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addVote(GwjVoteProjectRequest request, GwjBaseHouseOwnerDTO data) {
        //保存投票项目
        GwjVoteProject project = BeanUtil.copyProperties(request, GwjVoteProject.class);
        //投票状态
        project.setVoteStatus(GwjVoteStatusEnum.NOT_VOTE.getCode());
        //审批状态
        project.setAuditStatus(GwjVoteAuditStatusEnum.AGREE.getCode());
        //发起端类型
        project.setInitiateType(GwjVoteInitiateTypeEnum.GWJ_VOTE.getCode());
        //设置投票小区
        project.setCommunityId(data.getBaseCommunity().getCommunityId());
        //提交状态
        project.setSubmitStatus(GwjVoteSubmitStatusEnum.SUBMITTED.getCode());
        //街道
        project.setStreetId(data.getBaseCommunity().getStreetId());
        //地区
        project.setAreaId(data.getBaseCommunity().getAreaId());
        if (1 != insertVoteProject(project)) {
            throw new ServiceException("操作失败,保存投票失败");
        }
        //保存楼栋、房屋、业主
        data.setVoteId(project.getVoteId());
        saveHouseAndOwner(data);
        //保存公维金投票基本模板
        if (1 != voteTemplateService.addVoteTemplate(project.getVoteId(), project.getVoteTitle())) {
            throw new ServiceException("操作失败,保存投票模板失败");
        }
        return Boolean.TRUE;
    }

    /**
     * 投票审核（同意不同意）
     *
     * @param request 投票项目
     * @return 结果
     */
    @Override
    public int voteAudit(GwjVoteAuditRequest request, boolean isAgree) {
        //未提交无法审批
        GwjVoteProject voteProject = selectVoteProjectByVoteId(request.getVoteId());
        if (StringUtils.isNull(voteProject)) {
            throw new ServiceException("审核失败,查无投票信息");
        }
        if (voteProject.getVoteStatus().equals(GwjVoteStatusEnum.VOTE_ING.getCode()) && DateUtil.compare(DateUtils.getNowDate(), voteProject.getEndTime()) > 0) {
            throw new ServiceException("通知失败,投票已结束");
        }
        if (voteProject.getVoteStatus().equals(GwjVoteStatusEnum.VOTE_ING.getCode())) {
            throw new ServiceException("审核失败,投票正在进行中");
        }
        if (!voteProject.getSubmitStatus().equals(GwjVoteSubmitStatusEnum.SUBMITTED.getCode())) {
            throw new ServiceException("审核失败,投票未提交");
        }
        //同意
        GwjVoteProject project = new GwjVoteProject() {{
            //投票ID
            setVoteId(request.getVoteId());
            //审批意见
            setAuditOpinion(request.getAuditOpinion());
            if (isAgree) {
                //同意状态
                setAuditStatus(GwjVoteAuditStatusEnum.AGREE.getCode());
            } else {
                //不同意状态
                setAuditStatus(GwjVoteAuditStatusEnum.DISAGREE.getCode());
                //回退状态
                setSubmitStatus(GwjVoteSubmitStatusEnum.ROLLBACK.getCode());
            }
        }};
        return updateVoteProject(project);
    }

    /**
     * 保存房屋和业主数据
     *
     * @param data /
     */
    public void saveHouseAndOwner(GwjBaseHouseOwnerDTO data) {
        //插入房屋 分段插入
        List<List<GwjBaseHouse>> houseList = GwjConvertUtil.partition(data.getBaseHouses(), 100);
        houseList.forEach(l -> {
            List<GwjVoteHouse> voteHouses = BeanUtil.copyToList(l, GwjVoteHouse.class);
            voteHouses.forEach(vh -> {
                vh.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getRealName());
                vh.setCreateTime(DateUtils.getNowDate());
                vh.setSelectFlag(GwjBusinessHouseStatus.CONFIRM.getCode());
                vh.setVoteId(data.getVoteId());
            });
            if (voteHouseService.insertBatchVoteHouse(voteHouses) <= 0) {
                throw new ServiceException("保存房屋失败");
            }
        });
        //插入业主（结果表） 分段插入
        List<List<GwjBaseOwner>> ownerList = GwjConvertUtil.partition(data.getBaseOwners(), 100);
        ownerList.forEach(l -> {
            List<GwjVoteResult> voteResults = BeanUtil.copyToList(l, GwjVoteResult.class);
            voteResults.forEach(vo -> {
                vo.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getRealName());
                vo.setCreateTime(DateUtils.getNowDate());
                vo.setVoteType(GwjOwnerVoteTypeEnum.NOT_VOTE.getCode());
                vo.setCommunityId(data.getBaseCommunity().getCommunityId());
                vo.setVoteId(data.getVoteId());
            });
            if (voteResultService.insertBatchVoteResult(voteResults) <= 0) {
                throw new ServiceException("保存业主失败");
            }
        });
    }

    /**
     * 编辑投票
     *
     * @param isEVote 是否是电子投票
     * @param request 投票项目
     * @return 结果
     */
    @Override
    public boolean updateVote(GwjVoteProjectRequest request, boolean isEVote) {
        //校验时间参数
        if (isEVote && StringUtils.isNull(request.getPublicEndTime())) {
            throw new ServiceException("请选择公示截止时间");
        }
        if (DateUtil.compare(request.getStartTime(), request.getEndTime()) >= 0) {
            throw new ServiceException("投票结束时间必须大于投票发起时间");
        }
        if (isEVote) {
            if (DateUtil.compare(request.getEndTime(), request.getPublicEndTime()) >= 0) {
                throw new ServiceException("公示截止时间必须大于投票结束时间");
            }
        }
        //修改时投票信息是验证状态
        GwjVoteProject voteProject = selectVoteProjectByVoteId(request.getVoteId());
        if (StringUtils.isNull(voteProject)) {
            throw new ServiceException("操作失败,查无投票信息");
        }
        if (voteProject.getVoteStatus().equals(GwjVoteStatusEnum.CANCEL.getCode())) {
            throw new ServiceException("操作失败,投票已被取消");
        }
        //修改投票
        GwjVoteProject project = BeanUtil.copyProperties(request, GwjVoteProject.class);
        if (1 != updateVoteProject(project)) {
            throw new ServiceException("操作失败,更新投票项目失败");
        }
        return Boolean.TRUE;
    }

    /**
     * 取消投票
     *
     * @param voteId 投票ID
     * @return 结果
     */
    @Override
    public int voteCancel(Long voteId) {
        if (StringUtils.isNull(selectVoteProjectByVoteId(voteId))) {
            throw new ServiceException("取消失败,查无投票信息");
        }
        GwjVoteProject project = new GwjVoteProject() {{
            setVoteId(voteId);
            setVoteStatus(GwjVoteStatusEnum.CANCEL.getCode());
        }};
        return updateVoteProject(project);
    }

    /**
     * 短信通知
     *
     * @param voteId 投票ID
     * @return 结果
     */
    @Override
    public boolean voteSmsNotification(Long voteId) {
        GwjVoteProject voteProject = selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(voteProject)) {
            throw new ServiceException("通知失败,查无投票信息");
        }
        if (voteProject.getVoteStatus().equals(GwjVoteStatusEnum.VOTE_ING.getCode()) && DateUtil.compare(DateUtils.getNowDate(), voteProject.getEndTime()) > 0) {
            throw new ServiceException("通知失败,投票已结束");
        }
        if (!voteProject.getVoteStatus().equals(GwjVoteStatusEnum.VOTE_ING.getCode())) {
            throw new ServiceException("通知失败,投票未开始");
        }
        List<GwjVoteResult> owners = voteResultService.selectVoteResultList(new GwjVoteResultDTO() {{
            setVoteId(voteId);
            setSelectFlag(GwjBusinessHouseStatus.CONFIRM.getCode());
        }});
        //电话去重
        List<String> phones = owners.stream().map(o -> {
            String[] p = o.getOwnerPhone().split(",");
            String phone = null;
            for (String s : p) {
                phone = s;
            }
            return phone;
        }).distinct().collect(Collectors.toList());
        R<SysSms> r = remoteSmsService.sendSmsByPhonenumber(new SysSms() {{
            setSmsType(0);
            setPhonenumberList(phones);
            setSmsList(phones);
        }}, SecurityConstants.INNER);
        return !CheckRemoteServiceResultUtils.isCodeFail(r);
    }

    /**
     * 发起投票
     *
     * @param voteId 投票ID
     * @return 结果
     */
    @Override
    public int voteStart(Long voteId) {
        GwjVoteProject voteProject = selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(voteProject)) {
            throw new ServiceException("发起投票失败,查无投票信息");
        }
        if (voteProject.getVoteStatus().equals(GwjVoteStatusEnum.CANCEL.getCode())) {
            throw new ServiceException("发起投票失败,投票已被取消");
        }
        if (voteProject.getVoteStatus().equals(GwjVoteStatusEnum.VOTE_ING.getCode()) && DateUtil.compare(DateUtils.getNowDate(), voteProject.getEndTime()) > 0) {
            throw new ServiceException("操作失败,投票已结束");
        }
        if (voteProject.getVoteStatus().equals(GwjVoteStatusEnum.VOTE_ING.getCode())) {
            throw new ServiceException("发起投票失败,投票正在进行中");
        }
        if (DateUtil.compare(DateUtils.getNowDate(), voteProject.getStartTime()) < 0) {
            throw new ServiceException("发起投票失败,当前时间未到投票开始时间");
        }
        GwjVoteProject project = new GwjVoteProject() {{
            setVoteId(voteId);
            setVoteStatus(GwjVoteStatusEnum.VOTE_ING.getCode());
        }};
        return updateVoteProject(project);
    }

    /**
     * 校验业务状态
     *
     * @param bizNum 业务编号
     */
    @Override
    public void checkVoteProjectExist(Long bizNum) {
        //判断是否已经有投票项目了
        List<GwjVoteProject> projects = selectVoteProjectList(new GwjVoteProject() {{
            setBizNum(bizNum);
        }});
        if (StringUtils.isNotEmpty(projects)) {
            projects.forEach(p -> {
                if (p.getVoteStatus().equals(GwjVoteStatusEnum.NOT_VOTE.getCode()) || p.getVoteStatus().equals(GwjVoteStatusEnum.VOTE_ING.getCode())) {
                    throw new ServiceException("已存在未取消的投票项目");
                }
            });
        }
    }

    /**
     * 投票详情
     *
     * @param voteId 投票ID
     * @return 结果
     */
    @Override
    public GwjVoteProjectDetailDTO voteDetail(Long voteId) {
        //查询投票
        GwjVoteProject project = selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(project)) {
            throw new ServiceException("查无投票信息");
        }
        GwjVoteProjectDetailDTO dto = BeanUtil.copyProperties(project, GwjVoteProjectDetailDTO.class);
        if (project.getInitiateType().equals(GwjVoteInitiateTypeEnum.E_VOTE.getCode())) {
            //查询已选楼栋
            List<GwjVoteBuild> builds = voteBuildService.selectVoteBuildList(new GwjVoteBuild() {{
                setVoteId(voteId);
            }});
            if (StringUtils.isNotEmpty(builds)) {
                dto.setBuilds(BeanUtil.copyToList(builds, GwjVoteBuildDTO.class));
            }
        }
        return dto;
    }
}


